package com.fulihui.wgj.biz.impl;

import com.fulihui.common.enums.PlatformStatusEnum;
import com.fulihui.common.util.PlatformUtil;
import com.fulihui.weixinsdk.WeixinSDK;
import com.fulihui.weixinsdk.model.Template;
import com.fulihui.weixinsdk.request.group.GroupGetRequest;
import com.fulihui.weixinsdk.request.tag.TagGetRequest;
import com.fulihui.weixinsdk.request.template.TemplateGetRequest;
import com.fulihui.weixinsdk.request.user.UserListRequest;
import com.fulihui.weixinsdk.result.group.GroupGetResult;
import com.fulihui.weixinsdk.result.tag.TagGetResult;
import com.fulihui.weixinsdk.result.template.TemplateGetResult;
import com.fulihui.weixinsdk.result.user.UserListResult;
import com.fulihui.wgj.biz.SyncBiz;
import com.fulihui.wgj.dal.impala.mapper.UserInfoMapper;
import com.fulihui.wgj.dal.mybatis.domain.WxGroup;
import com.fulihui.wgj.dal.mybatis.domain.WxPlatform;
import com.fulihui.wgj.dal.mybatis.domain.WxTag;
import com.fulihui.wgj.dal.mybatis.repository.WxGroupRepository;
import com.fulihui.wgj.dal.mybatis.repository.WxPlatformRepository;
import com.fulihui.wgj.dal.mybatis.repository.WxTagRepository;
import com.fulihui.wgj.dal.mybatis.repository.WxTemplateRepository;
import com.fulihui.wgj.facade.msg.UserMsg;
import com.fulihui.wgj.mq.kafka.producer.KafkaProducer;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;
import java.util.Objects;


/**
 * 公众号数据同步服务
 */
@Component
public class SyncBizImpl implements SyncBiz {

    private static final Logger LOGGER = LoggerFactory.getLogger(SyncBizImpl.class);

    @Autowired
    private PlatformUtil platformUtil;
    @Autowired
    private WeixinSDK weixinSDK;
    @Autowired
    private KafkaProducer kafkaProducer;
    @Autowired
    WxTagRepository wxTagRepository;
    @Autowired
    WxGroupRepository wxGroupRepository;
    @Autowired
    WxTemplateRepository wxTemplateRepository;
    @Autowired
    WxPlatformRepository wxPlatformRepository;
    @Autowired
    UserInfoMapper userInfoMapper;

    @Override
    public void syncTag(String appId) {
        try {
            String cache = platformUtil.get(appId);
            if (StringUtils.isNotBlank(cache)) {
                TagGetRequest tagGetRequest = new TagGetRequest();
                tagGetRequest.setAccess_token(cache);
                TagGetResult tagGetResult = weixinSDK.invokeService(tagGetRequest);
                if (null != tagGetResult && !CollectionUtils.isEmpty(tagGetResult.getTags())) {
                    tagGetResult.getTags().forEach(tag -> {
                        WxTag wxTagQuery = new WxTag();
                        wxTagQuery.setAppId(appId);
                        wxTagQuery.setTagId(tag.getId().toString());
                        WxTag wxTagOne = wxTagRepository.queryOne(wxTagQuery);
                        if (Objects.isNull(wxTagOne)) {
                            WxTag wxTag = new WxTag();
                            wxTag.setAppId(appId);
                            wxTag.setTagId(tag.getId().toString());
                            wxTag.setName(tag.getName());
                            wxTag.setCount(Long.parseLong(tag.getCount().toString()));
                            wxTag.setGmtCreate(new Date());
                            wxTag.setGmtModified(new Date());
                            wxTagRepository.saveSelective(wxTag);
                        } else {
                            wxTagOne.setName(tag.getName());
                            wxTagOne.setCount(Long.parseLong(tag.getCount().toString()));
                            wxTagOne.setGmtModified(new Date());
                            wxTagRepository.updateSelective(wxTagOne);
                        }
                    });
                    LOGGER.info("syncTag complete. appId=[{}]", appId);
                }
            }
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        }
    }

    @Override
    public void syncGroup(String appId) {
        try {
            String cache = platformUtil.get(appId);
            if (StringUtils.isNotBlank(cache)) {
                GroupGetRequest groupGetRequest = new GroupGetRequest();
                groupGetRequest.setAccess_token(cache);
                GroupGetResult tagGetResult = weixinSDK.invokeService(groupGetRequest);
                if (null != tagGetResult && !CollectionUtils.isEmpty(tagGetResult.getGroups())) {
                    tagGetResult.getGroups().forEach(group -> {
                        WxGroup wxGroupQuery = new WxGroup();
                        wxGroupQuery.setAppId(appId);
                        wxGroupQuery.setGroupId(group.getId().toString());
                        WxGroup wxGroupOne = wxGroupRepository.queryOne(wxGroupQuery);
                        if (Objects.isNull(wxGroupOne)) {
                            WxGroup wxGroup = new WxGroup();
                            wxGroup.setGmtCreate(new Date());
                            wxGroup.setGmtModified(new Date());
                            wxGroup.setAppId(appId);
                            wxGroup.setGroupId(group.getId().toString());
                            wxGroup.setName(group.getName());
                            wxGroup.setCount(Long.parseLong(group.getCount().toString()));
                            wxGroupRepository.saveSelective(wxGroup);
                        } else {
                            wxGroupOne.setName(group.getName());
                            wxGroupOne.setCount(Long.parseLong(group.getCount().toString()));
                            wxGroupOne.setGmtModified(new Date());
                            wxGroupRepository.updateSelective(wxGroupOne);
                        }
                    });
                    LOGGER.info("syncGroup complete.appId=[{}]", appId);
                }
            }
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        }
    }

    @Override
    public void syncTemplate(String appId) {
        try {
            String cache = platformUtil.get(appId);
            if (StringUtils.isNotBlank(cache)) {
                TemplateGetRequest templateGetRequest = new TemplateGetRequest();
                templateGetRequest.setAccess_token(cache);
                // 微信返回的肯定是实时有效的
                TemplateGetResult templateGetResult = weixinSDK.invokeService(templateGetRequest);
                LOGGER.info("----syncTemplate appid:{},result:{}", appId, templateGetResult);
                if (Objects.nonNull(templateGetResult)) {
                    List<Template> templateList = templateGetResult.getTemplate_list();
                    wxTemplateRepository.syncTemplate(appId, templateList);
                    LOGGER.info("syncTemplate complete." + appId);
                }
            }
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        }
    }

    /**
     * TODO 需要考虑是否第一次授权就拉取用户 还是 后续手动拉取
     *
     * @param appId
     */
    @Override
    public void syncUserFirst(String appId) {
        String nextOpenId = null;
        // 第一次拉取用户 建表
        userInfoMapper.createTableWxUser(appId);

        do {
            try {
                String cache = platformUtil.get(appId);
                if (StringUtils.isBlank(cache)) {
                    LOGGER.error("syncUserFirst fail. PlatformCache not found.");
                    break;
                }

                UserListRequest userListRequest = new UserListRequest();
                userListRequest.setAccess_token(cache);
                userListRequest.setNext_openid(nextOpenId);

                UserListResult userListResult = weixinSDK.invokeService(userListRequest);

                nextOpenId = userListResult.getNext_openid();

                if (null != userListResult.getData()) {
                    List<List<String>> partition = Lists.partition(userListResult.getData().getOpenid(), 500);
                    partition.parallelStream().forEach(list -> {
                        UserMsg message = new UserMsg();
                        message.setAppId(appId);
                        message.setOpenIdList(list);
                        message.setNeedCheckExist(false);
                        kafkaProducer.sendPullUserOpenidsMsg(message);
                    });
                }
                if (StringUtils.isEmpty(nextOpenId)) {
                    // 拉取完毕 更新公众号信息
                    WxPlatform wxPlatform = new WxPlatform();
                    wxPlatform.setAppId(appId);
                    wxPlatform.setNextOpenid(userListRequest.getNext_openid());
                    wxPlatform.setStatus(PlatformStatusEnum.auth.getCode());
                    wxPlatform.setGmtModified(new Date());
                    wxPlatformRepository.updateWxPlatformByAppId(wxPlatform);
                    LOGGER.info("syncUserFirst complete." + appId);
                }
                Thread.sleep(100);
            } catch (Exception e) {
                nextOpenId = null;
                LOGGER.error(e.getMessage(), e);
            }
        } while (StringUtils.isNotBlank(nextOpenId));
    }

    @Override
    public void syncUser(String appId) {
        WxPlatform platform = wxPlatformRepository.queryOneByAppId(appId);
        String nextOpenId = platform.getNextOpenid();
        do {
            try {
                String cache = platformUtil.get(appId);
                if (StringUtils.isBlank(cache)) {
                    LOGGER.error("syncUser fail. PlatformCache not found.");
                    break;
                }

                UserListRequest userListRequest = new UserListRequest();
                userListRequest.setAccess_token(cache);
                userListRequest.setNext_openid(nextOpenId);

                UserListResult userListResult = weixinSDK.invokeService(userListRequest);

                nextOpenId = userListResult.getNext_openid();

                if (null != userListResult.getData()) {
                    List<List<String>> partition = Lists.partition(userListResult.getData().getOpenid(), 100);
                    partition.parallelStream().forEach(list -> {
                        UserMsg message = new UserMsg();
                        message.setAppId(appId);
                        message.setOpenIdList(list);
                        message.setNeedCheckExist(true);
                        kafkaProducer.sendPullUserOpenidsMsg(message);
                    });
                }

                if (StringUtils.isEmpty(nextOpenId)) {
                    WxPlatform wxPlatform = new WxPlatform();
                    wxPlatform.setAppId(appId);
                    wxPlatform.setNextOpenid(userListRequest.getNext_openid());
                    wxPlatform.setGmtModified(new Date());
                    wxPlatformRepository.updateWxPlatformByAppId(wxPlatform);
                    LOGGER.info("syncUser complete." + appId);
                }

                Thread.sleep(100);
            } catch (Exception e) {
                nextOpenId = null;
                LOGGER.error(e.getMessage(), e);
            }
        } while (StringUtils.isNotBlank(nextOpenId));
    }
}